package com.itools.core.service.impl;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.itools.core.base.CommonResult;
import com.itools.core.em.FmsCodeBean;
import com.itools.core.em.FmsConstants;
import com.itools.core.exception.AppException;
import com.itools.core.param.FmsUploadTokenParam;
import com.itools.core.result.*;
import com.itools.core.service.FileHandleService;
import com.itools.core.service.FmsAccessTokenService;
import com.itools.core.service.FmsBusinessTypeService;
import com.itools.core.service.FmsFileSystemService;
import com.itools.core.system.AbstractService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

/**
 * @project: itools-backend
 * @description:
 * @author: XUCHANG
 * @create: 2021-04-02 16:36
 */
@Service
public class FileHandleServiceImpl extends AbstractService implements FileHandleService {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    private FmsBusinessTypeService fmsBusinessTypeService;

    @Autowired
    private FmsAccessTokenService fmsAccessTokenService;

    @Autowired
    private FmsFileSystemService fmsFileSystemService;
    /**
     * 根据申请的文件token获取返回的上传文件的类型信息
     * KEY的名称itools:fms:file-token:fileToken
     * @param fileToken
     * @return
     */
    @Override
    public CommonResult<FmsUploadTokenResult> getFileDetailByToken(String fileToken) {
        //判断token是否不存在或者是过期
        boolean hasFileTokenKey = stringRedisTemplate.hasKey(FmsConstants.FILE_TOKEN_NAME_SPACE + fileToken).booleanValue();

        if (!hasFileTokenKey){
            throw new AppException(FmsCodeBean.FmsCode.FAIL_FILE_TOKEN.code);
        }
        String tokenParam = stringRedisTemplate.opsForValue().get(FmsConstants.FILE_TOKEN_NAME_SPACE + fileToken);
        FmsUploadTokenResult fmsUploadTokenResult = null;
        try {
            fmsUploadTokenResult = objectMapper.readValue(tokenParam,FmsUploadTokenResult.class);
        } catch (IOException e) {
            logger.error("JacKJson序列化失败",e);
        }
        return CommonResult.success(fmsUploadTokenResult);
    }

    /**
     * 文件策略为NIO
     * 执行文件写入和上传
     * @param file 文件
     * @param param 上传参数
     * @param uploadToken 访问token
     * @param originalFilename 原文件名称
     * @return
     */
    @Override
    public CommonResult<FmsFileUploadResult> saveFileForNio(MultipartFile file, FmsUploadTokenParam param, String uploadToken, String originalFilename) {
        param.setOriginalFilename(originalFilename);
        String uniqueId = fmsFileSystemService.saveFile(file, param);
        //文件上传成功，删除文件访问的token
        stringRedisTemplate.delete(FmsConstants.FILE_TOKEN_NAME_SPACE + uploadToken);
        FmsFileUploadResult fmsFileUploadResult = new FmsFileUploadResult();
        fmsFileUploadResult.setUniqueId(uniqueId);
        return CommonResult.success(fmsFileUploadResult);
    }

    /**
     * 保存多个
     * 文件策略为NIO
     * 执行文件写入和上传
     *
     * @param files            文件
     * @param uploadToken      访问token
     * @param uploadTokenParam 上传参数,文件的限制
     * @return
     */
    @Override
    public CommonResult<List<FmsMultipartFileResult>> saveFileForNio(MultipartFile[] files, String uploadToken, FmsUploadTokenParam uploadTokenParam) {

        CommonResult<List<FmsMultipartFileResult>> result = fmsFileSystemService.uploadFiles(files, uploadTokenParam);
        //文件上传成功，删除文件访问的token
        stringRedisTemplate.delete(FmsConstants.FILE_TOKEN_NAME_SPACE + uploadToken);
        return result;
    }

    /**
     * 将文件持久化到数据库
     *
     * @param file                文件
     * @param fmsUploadTokenParam 文件的类型等信息
     * @param uuid                文件唯一id
     * @return
     */
    @Override
    public CommonResult<String> createAndPersistDBRecord(MultipartFile file, FmsUploadTokenParam fmsUploadTokenParam, String uuid) {
        String andPersistDBRecord = fmsFileSystemService.createAndPersistDBRecord(file, fmsUploadTokenParam, uuid);
        return CommonResult.success(andPersistDBRecord);
    }

    /**
     * 获取文件访问路径
     *
     * @param uniqueIds      List文件唯一id
     * @param expiredTime    过期时间
     * @param maxAccessCount 最大访问次数
     * @param type           文件下载 download/展示 show
     * @return
     */
    @Override
    public CommonResult<List<FmsFileRecordPathResult>> getFileUrlByUniqueIds(List<String> uniqueIds, Integer expiredTime, Integer maxAccessCount, String type) {
        return fmsFileSystemService.getFileUrlByFileIds(uniqueIds,expiredTime,maxAccessCount,type);
    }

    /**
     * 根据文件唯一id查询文件的上传记录
     *
     * @param uniqueIds 文件唯一id
     * @return
     */
    @Override
    public CommonResult<List<FmsDetailRecordResult>> queryFileRecordsByUniqueIds(List<String> uniqueIds) {
        List<FmsDetailRecordResult> recordResults = fmsFileSystemService.queryFileRecordsByUniqueIds(uniqueIds);
        return CommonResult.success(recordResults);
    }

    /**
     * 根据文件唯一id查询文件的上传记录
     *
     * @param uniqueId 文件唯一id
     * @return
     */
    @Override
    public CommonResult<FmsDetailRecordResult> getFileUploadRecord(String uniqueId) {
        FmsDetailRecordResult fileUploadRecord = fmsFileSystemService.getFileUploadRecord(uniqueId);
        return CommonResult.success(fileUploadRecord);
    }

    /**
     * 下载文件
     *
     * @param fileAccessToken 文件的访问token
     * @param response
     * @param uniqueId        文件唯一id
     */
    @Override
    public void downloadFileNio(String fileAccessToken, HttpServletResponse response, String uniqueId) {
        fmsFileSystemService.downloadFile(fileAccessToken,response,uniqueId);
    }
}
